/**
 * 项目名：五位一体化工安全信息平台
 * 日期：    2019-12-09 17:24:08
 * Copyright (c) 2015- joysuch-版权所有
 */

package com.joysuch.wwyt.bp.service.impl;

import com.google.gson.Gson;
import com.joysuch.wwyt.bp.bean.BpExamStandardDetailBean;
import com.joysuch.wwyt.bp.bean.BpExamStandardEditBean;
import com.joysuch.wwyt.bp.bean.BpExamStandardListBean;
import com.joysuch.wwyt.bp.bean.BpExamStandardListBean.Search;
import com.joysuch.wwyt.bp.entity.BpDepart;
import com.joysuch.wwyt.bp.entity.BpExamStandard;
import com.joysuch.wwyt.bp.entity.BpTaskList;
import com.joysuch.wwyt.bp.entity.dsl.QBpExamStandard;
import com.joysuch.wwyt.bp.enums.TargetResponsibilityTypes;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.bp.repository.BpExamStandardDao;
import com.joysuch.wwyt.bp.repository.BpTaskListDao;
import com.joysuch.wwyt.bp.service.BpExamStandardService;
import com.joysuch.wwyt.bp.service.BpTaskListService;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.exception.BusinessRestrictionsException;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BizCodeGeneratorFacade;
import com.joysuch.wwyt.core.support.Context;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.*;

@Service
@Transactional
public class BpExamStandardServiceImpl implements BpExamStandardService {

    @Autowired
    private BpExamStandardDao dao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;

    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private BpExamStandardService bpExamStandardService;
    @Autowired
    private BpTaskListService taskListService;
    @Autowired
    private BpTaskListDao taskListDao;
    @Autowired
    private BpDepartDao bpDepartDao;

    @Override
    public BpExamStandard add(BpExamStandardEditBean entity) throws Exception {
        int count = dao.countByExamName(entity.getExamName());
        if (count > 0) {
            throw new IllegalArgumentException("此考核标准名称已存在");
        }
        BpExamStandard content = new BpExamStandard();
        // 考核标准名称
        content.setExamName(entity.getExamName());
        // 考核标准编号
        content.setNum(bizCodeGeneratorFacade.kaohebiaozhun());
        // 制定人ID
        content.setMakerId(entity.getMakerId());
        // 制定时间
        content.setMakeTime(entity.getMakeTime());
        // 考核项目集合
        content.setItemExam(entity.getItemExam());
        // 状态
        content.setStatus(TargetResponsibilityTypes.TO_BE_AUDITED.getId());
        String totalScore = calcScoreAndvalidateExamItemAnd(entity);
        // 考核条例总分
        if(bpExamStandardService.isNum(totalScore)){
            totalScore=bpExamStandardService.getNumberString(totalScore);
        }
        content.setItemTotalScore(totalScore);
        // //审核人ID
        // content.setAuditUserId(entity.getAuditUserId());
        // //审核时间
        // content.setAuditTime(entity.getAuditTime());
        // //审核意见
        // content.setAuditRemark(entity.getAuditRemark());
        content.setDepartId(entity.getDepartId());
        BpExamStandard save = dao.save(content);
        saveTaskList("考核标准制定", save);
        return save;
    }

    @Override
    public Boolean isNum(String str) {
        try {
            new BigDecimal(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public String getNumberString(String str) {
        if (str.equals("0.0")) {
            return "0";
        }
        if (str.startsWith("0") || str.length() > 512) {
            return str;
        }
        Double d = Double.valueOf(str);
        NumberFormat nf = NumberFormat.getInstance();
        String s = nf.format(d);
        if (s.indexOf(",") >= 0) {
            s = s.replace(",", "");
        }
        return s;
    }

    /**
     * @param entity
     * @return
     */
    protected String calcScoreAndvalidateExamItemAnd(BpExamStandardEditBean entity) {
        Gson gson = new Gson();
        List<Map<String, Object>> itemExamList = gson.fromJson(entity.getItemExam(), ArrayList.class);
        BigDecimal totalScore = new BigDecimal(0);
        int i = 1;
        for (Map<String, Object> tempMap : itemExamList) {
            try {
                Double row = (Double) tempMap.get("itemId");
                Assert.hasText((String) tempMap.get("itemName"), String.format("第%d行考核项目名称不能为空", row.intValue()));
                if (tempMap.get("itemScore") != null && StringUtils.isNotBlank(tempMap.get("itemScore").toString())) {
                    String itemScore = tempMap.get("itemScore").toString();
                    totalScore = totalScore.add(new BigDecimal(itemScore));
                }

//                if (!FloatUtil.judgeFloat(s)) {
//                    throw new NumberFormatException();
//                }
                //Assert.isTrue(s > 0, tempMap.get("itemName") + " 分值必须大于0");
                i++;
            } catch (NumberFormatException e) {
                throw new IllegalArgumentException("考核项目第" + i + "行,请重新填写正确的分值", e);
            } catch (Exception e) {
                throw new IllegalArgumentException(e.getMessage(), e);
            }
        }
        return totalScore.toString();
    }

    private void saveTaskList(String module, BpExamStandard save) {
        // 添加代办事项
        BpTaskList bpTaskList = new BpTaskList();
        bpTaskList.setDataId(save.getId());
        bpTaskList.setUserId(save.getAuditUserId());
        bpTaskList.setModule(module);
        taskListDao.save(bpTaskList);
    }

    /**
     * @param entity
     * @throws Exception
     */
    @Override
    public void update(BpExamStandardEditBean entity) throws Exception {
        BpExamStandard content = dao.findById(entity.getId()).get();
        if (content != null) {
            if (!entity.getExamName().equals(content.getExamName())) {
                int count = dao.countByExamName(entity.getExamName());
                if (count > 0) {
                    throw new IllegalArgumentException("此考核标准名称已存在");
                }
            }
            // 考核标准名称
            content.setExamName(entity.getExamName());
            // 制定人ID
            content.setMakerId(entity.getMakerId());
            // 制定时间
            content.setMakeTime(entity.getMakeTime());
            // 考核项目集合
            content.setItemExam(entity.getItemExam());
            // 状态
            content.setStatus(TargetResponsibilityTypes.TO_BE_AUDITED.getId());
            String totalScore = calcScoreAndvalidateExamItemAnd(entity);
            // 考核条例总分
            content.setItemTotalScore(totalScore);
            // 审核人ID
            content.setAuditUserId(null);
            // 审核时间
            content.setAuditTime(null);
            // 审核意见
            content.setAuditRemark(null);
            content.setDepartId(entity.getDepartId());
            dao.save(content);
        }
    }

    @Override
    public Page<BpExamStandardListBean> findByPage(Pageable page, Search condition) {
        Predicate predicate = prepareListSearchCondition(condition);

        page = PageDataUtils.addOrderByDesc(page, "id");
        Page<BpExamStandard> data = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);

        return PageDataUtils.convertPageData(data, new PageDataConvert<BpExamStandardListBean, BpExamStandard>() {

            @Override
            public BpExamStandardListBean convert(BpExamStandard f) {
                BpExamStandardListBean bean = new BpExamStandardListBean();

                // ID，主键
                bean.setId(f.getId());

                // 考核标准名称
                bean.setExamName(f.getExamName());

                // 考核标准编号
                bean.setNum(f.getNum());

                // 制定人ID
                bean.setMakerId(f.getMakerId());
                if (f.getMakerId() != null) {
                    Optional<BaseUser> obu = baseUserDao.findById(f.getMakerId());
                    if (obu.isPresent()) {
                        bean.setMaker(obu.get().getRealName());
                    }
                }

                // 制定时间
                if (f.getMakeTime() != null) {
                    bean.setMakeTime(SimpleDateFormatCache.getYmd().format(f.getMakeTime()));
                }

                // 考核项目集合
                bean.setItemExam(f.getItemExam());

                // 状态
                bean.setStatus(TargetResponsibilityTypes.findByID(f.getStatus()).getName());

                // 考核条例总分
                bean.setItemTotalScore(f.getItemTotalScore());

                // 审核人ID
                bean.setAuditUserId(f.getAuditUserId());
                if (f.getAuditUserId() != null) {
                    BaseUser baseUser = baseUserDao.findById(f.getAuditUserId()).get();
                    bean.setAuditUserName(baseUser.getRealName());
                }

                // 审核时间
                if (f.getAuditTime() != null) {
                    bean.setAuditTime(SimpleDateFormatCache.getYmd().format(f.getAuditTime()));
                }

                // 责任部门
                if (f.getDepartId() != null) {
                    BpDepart bpDepart = bpDepartDao.findById(f.getDepartId()).get();
                    bean.setDepartName(bpDepart.getName());
                }

                // 审核意见
                bean.setAuditRemark(f.getAuditRemark());

                return bean;
            }

        });
    }

    private Predicate prepareListSearchCondition(Search condition) {
        QBpExamStandard qBpExamStandard = QBpExamStandard.bpExamStandard;
        Predicate predicate = null;
        if (condition.getExamName() != null) {
            predicate = qBpExamStandard.examName.like("%" + condition.getExamName() + "%");
        }
        if (condition.getStatus() != null) {
            String[] stateStr = condition.getStatus().split(",");
            List<Integer> ids = new ArrayList<>();
            for (int i = 0; i < stateStr.length; i++) {
                ids.add(TargetResponsibilityTypes.findByName(stateStr[i]).getId());
            }
            BooleanExpression in = qBpExamStandard.status.in(ids);
            predicate = predicate == null ? in : ExpressionUtils.and(predicate, in);
        }
        if (condition.getDepartId() != null) {
            BooleanExpression and = qBpExamStandard.departId.eq(condition.getDepartId());
            predicate = predicate == null ? and : ExpressionUtils.and(predicate, and);
        }
        return predicate;
    }

    @Override
    public void delete(Long id) throws BusinessRestrictionsException {
        // 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用。不能删除时将抛出业务异常
        checkBussinessRestrictions(id);
        dao.deleteById(id);
    }

    /**
     * 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用
     *
     * @param id 要删除的业务ID
     * @throws BusinessRestrictionsException 抛出的业务异常
     */
    private void checkBussinessRestrictions(Long id) throws BusinessRestrictionsException {

    }

    @Override
    public BpExamStandard findById(Long id) {
        return dao.findById(id).get();
    }

    @Override
    public BpExamStandardDetailBean getById(Long id) {
        BpExamStandard entity = findById(id);
        BpExamStandardDetailBean bean = new BpExamStandardDetailBean();
        // ID，主键
        bean.setId(entity.getId());

        // 考核标准名称
        bean.setExamName(entity.getExamName());

        // 考核标准编号
        bean.setNum(entity.getNum());

        // 制定人ID
        bean.setMakerId(entity.getMakerId());
        if (entity.getMakerId() != null) {
            bean.setMaker(baseUserDao.findById(entity.getMakerId()).get().getRealName());
        }

        // 制定时间
        if (entity.getMakeTime() != null) {
            bean.setMakeTime(SimpleDateFormatCache.getYmd().format(entity.getMakeTime()));
        }

        // 考核项目集合
        bean.setItemExam(entity.getItemExam());

        // 状态
        bean.setStatus(TargetResponsibilityTypes.findByID(entity.getStatus()).getName());

        // 考核条例总分
        bean.setItemTotalScore(entity.getItemTotalScore());

        // 审核人ID
        bean.setAuditUserId(entity.getAuditUserId());
        if (entity.getAuditUserId() != null) {
            bean.setAuditUserName(baseUserDao.findById(entity.getAuditUserId()).get().getRealName());
        }

        // 审核时间
        if (entity.getAuditTime() != null) {
            bean.setAuditTime(SimpleDateFormatCache.getYmd().format(entity.getAuditTime()));
        }

        // 审核意见
        bean.setAuditRemark(entity.getAuditRemark());

        if (entity.getDepartId() != null) {
            BpDepart bpDepart = bpDepartDao.findById(entity.getDepartId()).get();
            if (bpDepart != null){
                bean.setDepartName(bpDepart.getName());
            }
            bean.setDepartId(entity.getDepartId());
        }

        return bean;
    }

    @Override
    public void changeStateByAudit(Long id, Boolean isPass, String auditRemark) {
        BpExamStandard content = dao.findById(id).get();
        if (content != null) {
            if (content.getStatus() == TargetResponsibilityTypes.TO_BE_AUDITED.getId()
                    || content.getStatus() == TargetResponsibilityTypes.AUDIT_FAILED.getId()) {
                // 如果是待申请或者之前审核失败，则更新成等待审核
                content.setStatus(TargetResponsibilityTypes.AUDIT_WAIT.getId());
                List<BpTaskList> byId = taskListService.findById(content.getId());
                if (byId != null) {
                    for (BpTaskList bpTaskList : byId) {
                        bpTaskList.setState(0);
                        bpTaskList.setDetail("考核标准审核");
                        bpTaskList.setHandleRemark("考核标准审核提交");
                        // 处理当前时间
                        bpTaskList.setHandleTime(new Date());
                        bpTaskList.setHandleUserId(Context.getCurrentUserId());
                        taskListDao.save(bpTaskList);
                    }
                }
            } else if (content.getStatus() == TargetResponsibilityTypes.AUDIT_WAIT.getId()) {
                // 如果是等待审核，根据 isPass 更新
                if (isPass) { // 更新成审核通过
                    content.setAuditUserId(Context.getCurrentUserId());
                    content.setAuditRemark(auditRemark);
                    content.setAuditTime(new Date());
                    content.setStatus(TargetResponsibilityTypes.AUDIT_PASS.getId());
                    List<BpTaskList> byId = taskListService.findById(content.getId());
                    if (byId != null) {
                        for (BpTaskList bpTaskList : byId) {
                            bpTaskList.setState(2);
                            bpTaskList.setDetail("考核评审");
                            bpTaskList.setHandleRemark("考核评审通过");
                            // 处理当前时间
                            bpTaskList.setHandleTime(new Date());
                            bpTaskList.setHandleUserId(Context.getCurrentUserId());
                            taskListDao.save(bpTaskList);
                        }
                    }
                } else { // 更新成审核不通过
                    content.setAuditUserId(Context.getCurrentUserId());
                    content.setAuditRemark(auditRemark);
                    content.setAuditTime(new Date());
                    content.setStatus(TargetResponsibilityTypes.AUDIT_FAILED.getId());
                    List<BpTaskList> byId = taskListService.findById(content.getId());
                    if (byId != null) {
                        for (BpTaskList bpTaskList : byId) {
                            bpTaskList.setState(3);
                            bpTaskList.setDetail("考核评审");
                            bpTaskList.setHandleRemark("考核评审未通过");
                            // 处理当前时间
                            bpTaskList.setHandleTime(new Date());
                            bpTaskList.setHandleUserId(Context.getCurrentUserId());
                            taskListDao.save(bpTaskList);
                        }
                    }
                }
            } else {
                // 其他状态，不进行更改
                return;
            }
            dao.save(content);
        }
    }

}
